package com.unitd.frame.sso.web.interceptor;

import com.unitd.frame.comm.utils.StringUtils;
import com.unitd.frame.sso.annotation.Action;
import com.unitd.frame.sso.annotation.Permission;
import com.unitd.frame.sso.common.config.SSOConfig;
import com.unitd.frame.sso.common.helper.SSOHelper;
import com.unitd.frame.sso.common.shiro.impl.SSOAuthToken;
import com.unitd.frame.sso.common.token.SSOToken;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @desc sso_shiro 权限拦截器（必须在 sso 拦截器之后执行）
 * @filename SSOShiroInterceptor.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2016/10/18
 */
public class SSOShiroInterceptor extends SSOPermissionInterceptor {

	private static final Logger logger = LoggerFactory.getLogger(SSOShiroInterceptor.class.getName());

	/**
	 * @desc 用户权限验证
	 * 执行登录权限验证,此方法在调用SprigMVC的Controller的处理方法之前进行拦截调用
	 * @param request http请求对象
	 * @param response http响应对象
	 * @param handler 默认的SSO Handler拦截器
	 * @return 登录用户是否有权限
	 * @throws Exception
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		if (handler instanceof HandlerMethod) {
			SSOToken token = SSOHelper.attrToken(request);
			if (token == null) {
				return true;
			}

			/* shiro 会话管理 */
			Subject currentUser = SecurityUtils.getSubject();
			Session session = currentUser.getSession(false);
			if (session != null) {
				session.touch();
			}

			/* shiro 登录认证 */
			if (!currentUser.isAuthenticated()) {
				currentUser.login(new SSOAuthToken(token));
				logger.info(" shiro 权限验证登陆成功!");
			}

			/* URL 权限认证 */
			if (SSOConfig.getInstance().isPermissionUri()) {
				String uri = request.getRequestURI();
				if (uri == null || currentUser.isPermitted(uri)) {
					return true;
				}
			}

			/* 注解权限认证 */
			HandlerMethod handlerMethod = (HandlerMethod) handler;
			Method method = handlerMethod.getMethod();
			Permission pm = method.getAnnotation(Permission.class);
			if (pm != null) {
				if (pm.action() == Action.Skip) {
					/* 忽略拦截 */
					return true;
				} else if(StringUtils.isNotBlank(pm.value()) && currentUser.isPermitted(pm.value())) {
					/* 权限合法 */
					return true;
				}
			}

			/* 无权限访问 */
			return unauthorizedAccess(request, response);
		}
		return true;
	}
}